﻿using Antlr4.Runtime.Tree;
using System;
using System.Collections.Generic;
using System.Text;
using TT.Compiler.Node;

namespace TT.Compiler.Define
{
    //定义是对AST的简单处置，增加语义的时候，切换为不含AST的对象
    public enum TypeDefineType
    {
        Documents,
        Struct,
        Enum,
        TypeName,
        Class,
    }
    public enum Modifier
    {
        None,
        Const,
        Share,
        Export,
    }
    public class TypeDefine : IDocNode
    {

        public const string glabolDefineName = "::glabol";

        string _namespace;
        string _name;

        public TypeDefine(IParseTree ast, TypeDefineType _type, string _namespace, string _name)
        {
            this.Ast = ast;
            this._namespace = _namespace;
            this._name = _name;
            this.Type = _type;
        }

        public static TypeDefine CreateGlabol()
        {
            return new TypeDefine(null, TypeDefineType.Documents, "", glabolDefineName);
        }
        public static TypeDefine CreateDocument(IParseTree ast)
        {
            return new TypeDefine(ast, TypeDefineType.Documents, "", glabolDefineName);
        }
        public string FullName
        {
            get
            {
                if (_namespace == "")
                    return _name;
                else
                    return _namespace + "." + _name;
            }
        }
        public IParseTree Ast
        {
            get;
            private set;
        }
        public TypeDefineType Type
        {
            get;
            private set;
        }
        public Modifier Modifier
        {
            get;
            set;
        }
        public string BaseTypeRef
        {
            get;
            set;
        }

        public IReadOnlyCollection<FieldDefine> Fields
        {
            get
            {
                return fields.Values;
            }
        }
        public IReadOnlyCollection<FuncDefine> Funcs
        {
            get
            {
                return funcs.Values;
            }
        }
        public IReadOnlyCollection<TypeDefine> GetAllOtherDefines()
        {
            List<TypeDefine> result = new List<TypeDefine>();
            foreach (var t in otherTypes.Values)
            {
                result.Add(t);

                var tsub = t.GetAllOtherDefines();
                result.AddRange(tsub);
            }
            return result.AsReadOnly();
        }
        Dictionary<string, FieldDefine> fields = new Dictionary<string, FieldDefine>();
        Dictionary<string, FuncDefine> funcs = new Dictionary<string, FuncDefine>();
        Dictionary<string, TypeDefine> otherTypes = new Dictionary<string, TypeDefine>();

        public void AddField(FieldDefine field)
        {
            if (this.fields.ContainsKey(field.Name))
                throw new Exception("already have a filed named:" + field);
            this.fields[field.Name] = field;
        }
        public void AddFunc(FuncDefine func)
        {
            if (this.funcs.ContainsKey(func.Name))
                throw new Exception("already have a FuncDefine named:" + func);
            this.funcs[func.Name] = func;
        }
        public void AddOtherType(TypeDefine type)
        {
            if (this.otherTypes.ContainsKey(type.FullName))
                throw new Exception("already have a FuncDefine named:" + type.FullName);
            this.otherTypes[type.FullName] = type;
        }
    }
    public class FieldDefine : IDocNode
    {
        string _name;
        string _namespace;
        public FieldDefine(IParseTree ast, string parent_namespace, string _name)
        {
            this.Ast = ast;
            this._namespace = parent_namespace;
            this._name = _name;
        }
        public string Name
        {
            get
            {
                return _name;
            }
        }
        public string FullName
        {
            get
            {
                return _namespace + "." + _name;
            }
        }
        public IParseTree Ast
        {
            get;
            private set;
        }
        public object DefaultValue
        {
            get;
            set;
        }
    }

    public class FuncDefine : IDocNode
    {
        string _name;
        string _namespace;
        public FuncDefine(IParseTree ast, string parent_namespace, string _name)
        {
            this.Ast = ast;
            this._namespace = parent_namespace;
            this._name = _name;
        }
        public string Name
        {
            get
            {
                return _name;
            }
        }
        public string FullName
        {
            get
            {
                return _namespace + "." + _name;
            }
        }
        public IParseTree Ast
        {
            get;
            private set;
        }
    }



}
